import requests
import execjs
import time
from bs4 import BeautifulSoup
import re
import json

from PIL import Image


class dfcf:
    def __init__(self):
        self.js_path="enc.js"
        self.html_path="ctxid.html"
        self.headers = {
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,ar;q=0.7",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "Pragma": "no-cache",
            "Referer": "https://exaccount2.eastmoney.com/",
            "Sec-Fetch-Dest": "script",
            "Sec-Fetch-Mode": "no-cors",
            "Sec-Fetch-Site": "same-site",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
            "sec-ch-ua": "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\", \"Microsoft Edge\";v=\"138\"",
            "sec-ch-ua-mobile": "?0",
            "sec-ch-ua-platform": "\"Windows\""
        }

        self.cookies = {
            "qgqp_b_id": "af4a3d01781b5555726d9a17e425be7a",
            "st_nvi": "2xfzbOLOA9PSvGMSOq0F6856a",
            "nid": "04d51e4d408a5c3c863d17873895a224",
            "nid_create_time": "1754271580335",
            "gvi": "a5R5YyyjtEfOf8i6-mdDl6c36",
            "gvi_create_time": "1754271580335",
            "p_origin": "https%3A%2F%2Fpassport2.eastmoney.com",
            "st_si": "70929526663838",
            "st_pvi": "67053581251557",
            "st_sp": "2025-08-04%2009%3A39%3A40",
            "st_inirUrl": "https%3A%2F%2Fpassport2.eastmoney.com%2F",
            "st_sn": "1",
            "st_psi": "2025080409520213-0-4444453367",
            "st_asi": "delete"
        }
    def init_js(self):
        with open(self.js_path, "r", encoding="utf-8") as f:
            js_code = f.read()
        ctx = execjs.compile(js_code)
        return ctx
    def init(self):
        url = "https://exaccount2.eastmoney.com/home/Login4"
        params = {
            "rc": "354855057"
        }
        response = requests.get(url, headers=self.headers, cookies=self.cookies, params=params)
        html = response.text
        capt_app_id = None
        match = re.search(r"var\s+CaptAppId\s*=\s*'(\d+)';", html)
        if match:
            capt_app_id = match.group(1)
            print("解析到的 CaptAppId:", capt_app_id)
        else:
            print("CaptAppId 没找到")
        soup = BeautifulSoup(html, 'html.parser')
        ctxid = soup.find('input', id='hdAccountCaptContextId')
        if ctxid is None:
            print("ctxid not found")
            return
        print("Login4 status==>",response.status_code)
        print("Login4 ctxid['value']==>",ctxid['value'])
        with open(self.html_path,"w",encoding="utf-8") as f:
            f.write(html)
            print("Login4 html saved")
        cid=ctxid['value']
        return cid,capt_app_id

    def get_bg(self, ctxid):
        ctx = self.init_js()  # 注意这里要加括号
        req = ctx.call("get_req", ctxid)
        print("req==>", req)
        url = "https://smartvcode2.eastmoney.com/Titan/api/captcha/get"
        params = {
            "callback": "cb",
            "ctxid": ctxid,
            "request": req,
            "_": str(int(time.time() * 1000))
        }
        response = requests.get(url, headers=self.headers, cookies=self.cookies, params=params)
        print("请求结果:", response.text)
        if response.status_code != 200:
            print("请求失败，状态码：", response.status_code)
            return None
        return response.text

    def parse_captcha_response(self, response_text):
        import json, re

        # 保证字符串没有前后空白
        response_text = response_text.strip()

        # 1. 提取json内容
        match = re.search(r"cb\(\s*(\{.*?\})\s*\)\s*;", response_text, re.DOTALL)
        if not match:
            print("无法找到 JSON 数据")
            print("实际内容为", repr(response_text))
            return None

        json_str = match.group(1).strip()
        print("要解码的json_str:", repr(json_str))  # 调试用
        try:
            data = json.loads(json_str)
        except Exception as e:
            print("json.loads 失败：", e)
            print('出错内容如下：')
            print(json_str)
            return None

        if data.get("ReturnCode") != "0":
            print("接口返回失败: ", data.get("Msg"))
            return None

        captcha_type = data["Data"].get("CaptchaType")
        captcha_info_str = data["Data"].get("CaptchaInfo")

        if isinstance(captcha_info_str, dict):
            captcha_info = captcha_info_str
        else:
            try:
                captcha_info = json.loads(captcha_info_str)
            except Exception as e:
                print("嵌套 json.loads 失败：", e)
                print('出错内容如下：')
                print(captcha_info_str)
                return None

        if captcha_type == "slide":
            static_servers = captcha_info.get("static_servers", [])
            server = ('https://' if captcha_info.get("https") else 'http://') + static_servers[
                0] if static_servers else ""
            img = {
                "bg": server + captcha_info.get("bg") if captcha_info.get("bg") else None,
                "slice": server + captcha_info.get("slice") if captcha_info.get("slice") else None,
                "fullbg": server + captcha_info.get("fullbg") if captcha_info.get("fullbg") else None,
                "ypos": captcha_info.get("ypos", 0),
                "height": captcha_info.get("height", 160),
                "type": "slide",
                "captchaContextId": captcha_info.get("captchaContextId")
            }
            return img
        elif captcha_type == "init":
            return {"type": "init"}
        else:
            print("未知的 CaptchaType:", captcha_type)
            return None



if __name__ == '__main__':
    dfcf_obj = dfcf()
    ctxid, capt_app_id = dfcf_obj.init()

    # 第一次请求
    response_text = dfcf_obj.get_bg(ctxid)
    result = dfcf_obj.parse_captcha_response(response_text)
    print('第1次返回:', result)

    # 如果首次为无感（init），自动再调一次
    if result is not None and result.get("type") == "init":
        response_text = dfcf_obj.get_bg(ctxid)
        result = dfcf_obj.parse_captcha_response(response_text)
        print('第2次返回:', result)

    # 最终无论类型还是init还是slide都能看到内容
    print('最终结果:', result)